/*
 *   Clovis
 *   Copyright (C) 2008 SFWOL
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "Node.h"
#include "Converter.h"

namespace clovis {

	namespace core {


        Node::Node(){
            this->value = NULL;
            sons.clear();
        }

        Node::Node(ClovisVariable * value){
            this->value = value;
            sons.clear();
        }

        Node::~Node(){
            Node * tmp;
            for(std::list<Node*>::iterator iter = sons.begin() ; iter != sons.end() ; ++iter){
                tmp = *iter;
                delete tmp;
            }
            delete value;
            sons.clear();
        }

        void Node::setValue(ClovisVariable * value){
            if (this->value == NULL)
                delete this->value;
            this->value = value;
        }

        ClovisVariable * Node::getValue(){
            return this->value;
        }

        Node * Node::addNode(ClovisVariable * value , NODE_ADD_METHOD methode ){
            Node * tmp = NULL;
            if (methode == REPLACE){
                tmp = getNode(value->getName());
                if (tmp)
                    tmp->setValue(value);
                else{
                    tmp = new Node(value);
                    sons.push_back(tmp);
                }
            }else{
                tmp = new Node(value);
                sons.push_back(tmp);
            }
            return tmp;
        }

        Node * Node::getNode(ClovisVariable * value){
            Node * tmp;
            for(std::list<Node*>::iterator iter = sons.begin() ; iter != sons.end() ; ++iter){
                tmp = *iter;
	            if (tmp->getValue() == value)
                    return tmp;
            }
            return NULL;
        }

        Node * Node::getNode(CString path){
           return getPath(path,this);
        }

        Node * Node::getPath(CString path , Node * node){
            //std::cout << "J'ai fais un appel " << path.toStdString() << std::endl;
            CString tmp;
            ClovisVariable * tmp2;
            Node * tmp3;
            std::vector<CString> lst = path.explode(".");
            tmp = lst.front();
            //std::cout << "Je suis sur : " << node->getValue()->getName() << std::endl;
            if (node->sons.size()){
                for(std::list<Node*>::iterator iter = node->sons.begin() ; iter != node->sons.end() ; ++iter){
                    tmp3 = *iter;
                    tmp2 = tmp3->getValue();
                    //std::cout << tmp.toStdString() << " == " << tmp2->getName() ;
                    if ( tmp.toStdString() == tmp2->getName() ){
                        //std::cout << " ---> Ok" << std::endl;
                        if (lst.size() == 1){
                            //std::cout << "J'ai finis le parcours je retourne le noeud courant" << std::endl;
                            return tmp3;
                        }
                        //std::cout << "J'ai encore du chemin a parcourir" << std::endl;
                        return getPath(path.substr(tmp.size() + 1 , path.size() - tmp.size()), tmp3);
                    }
                    //std::cout << " ---> Pas ok" << std::endl;
                }

            }

            return NULL;

        }

        std::list<Node*> Node::getNodes(std::list<Node*> liste , CString name , Node * node , CInteger limit){
            Node * temp;
            if (node->value->getName() == name.toStdString()) // Si le noeud fais parti du lot
                liste.push_back(node);

            if (limit > 0){ // Si la limite n'est pas atteinte
                if (node->sons.size()){ // S'il y a des noeuds fils
                    // on parcours chaque fils ...
                    for(std::list<Node*>::iterator iter = node->sons.begin() ; iter != node->sons.end() ; ++iter){
                        temp = *iter;
                        liste = getNodes(liste,name,temp,limit-1);
                    }
                }
            }
            return liste;
        }

        void Node::print(CString path){
            Node * temp;
            std::cout << path.toStdString() << "." << value->getName() << std::endl;
            for(std::list<Node*>::iterator iter = sons.begin() ; iter != sons.end() ; ++iter){
                temp = *iter;
                temp->print( path + "." + value->getName() );
            }

        }

         void Node::addTree(Node * tree , NODE_ADD_METHOD method){
            Node * n = addNode(tree->getValue() , method);
            Node * temp;
            for(std::list<Node*>::iterator iter = tree->sons.begin() ; iter != tree->sons.end() ; ++iter){
                temp = *iter;
                n->addTree(temp,method);
            }
         }

         std::list<Node*> Node::getSons(){

            return sons;

         }

	};

};



